package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.crm.abstracts.AbstractCrmAddDataService;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.enums.FundAccountFlowTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.service.dynamic.help.DynamicHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.vo.BeforeSaveVO;
import com.xbongbong.pro.formdata.pojo.vo.SaveVO;
import com.xbongbong.saas.domain.entity.FundAccountFlowEntity;
import com.xbongbong.saas.domain.entity.FundTransferEntity;
import com.xbongbong.saas.domain.entity.FundTransferSubDataEntity;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.FundAccountFlowModel;
import com.xbongbong.saas.model.FundTransferModel;
import com.xbongbong.saas.model.FundTransferSubDataModel;
import com.xbongbong.saas.service.FundTransferService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Description： 资金调拨单service实现层
 * author: 汪腾伟
 * Date: Created in 2021/5/24 15:02
 */
@Service("fundTransferDataServiceImpl")
public class FundTransferDataServiceImpl extends AbstractCrmAddDataService {

    private static final Logger LOG = LoggerFactory.getLogger(FundTransferDataServiceImpl.class);
    @Resource
    private FundTransferModel fundTransferModel;
    @Resource
    private FundTransferService fundTransferService;
    @Resource
    private FundAccountFlowModel fundAccountFlowModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private DynamicHelp dynamicHelp;
    @Resource
    private FundTransferSubDataModel fundTransferSubDataModel;

    @Override
    public List<Integer> businessList() {
        return Arrays.asList(XbbRefTypeEnum.FUND_TRANSFER.getCode());
    }

    @Override
    public void afterSaveLog(FormDataAddDTO formDataAddDTO, PaasFormEntityExt paasFormEntityExt, PaasFormDataEntity newPaasFormDataEntity, SaveVO saveVO, BeforeSaveVO beforeSaveVO) throws XbbException {
        boolean isImport = Objects.equals(1, formDataAddDTO.getIsImport());
        if (isImport) {
            return;
        }
        String serialNo = newPaasFormDataEntity.getSerialNo();
        saveLogger(formDataAddDTO, newPaasFormDataEntity, serialNo, XbbRefTypeEnum.FUND_TRANSFER.getName(), OperateModuleTypeEnum.FUND_TRANSFER, saveVO, beforeSaveVO);
    }

    @Override
    public void apiHook(FormDataAddDTO formDataAddDTO, SaveVO saveVO, BeforeSaveVO beforeSaveVO) throws XbbException {

    }

    @Override
    public SaveVO save(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Long dataId = 0L;
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        Long refundId = null;
        try {
            UserVO userVO = getUserName(formDataAddDTO, paasFormDataEntity);
            Integer noApprovalRequired = beforeSaveVO.getNoApprovalRequired();
            if (Objects.equals(1, noApprovalRequired)) {
                JSONObject data = paasFormDataEntity.getData();
                FormDataUtil.removeSystemData(data);
                Object richTextData = removeRichText(data);
                FundTransferEntity fundTransferEntity = new FundTransferEntity();
                BeanUtil.copyProperties(paasFormDataEntity, fundTransferEntity);
                fundTransferModel.insert(fundTransferEntity);
                dataId = fundTransferEntity.getId();
                // 设置属性用于返回
                setPartialAttributes(dataId, fundTransferEntity.getSubFormData(), fundTransferEntity.getData(), fundTransferEntity.getAddTime(),
                        fundTransferEntity.getUpdateTime(), paasFormDataEntity, beforeSaveVO);

                //文件柜数据保存
                saveFile(formDataAddDTO, paasFormDataEntity, userVO);
                //富文本数据保存
                saveRichText(formDataAddDTO, paasFormDataEntity, richTextData);
            }
            return new SaveVO(noApprovalRequired, paasFormDataEntity, dataId, userVO, refundId);
        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public void saveRollBack(Long id, String corpid, Integer saasMark, Integer businessType) throws XbbException {
        if (id == null || id == 0 || corpid == null || saasMark == null) {
            return ;
        }
        IndexTypeEnum indexTypeEnum = getIndexTypeEnum(corpid, saasMark, businessType);
        //删除主表es数据
        physicalDeleteFormData(id, corpid, indexTypeEnum);
        // 子表单的删除
        List<FundTransferSubDataEntity> fundTransferSubDataEntities = fundTransferSubDataModel.getByDataId(id, corpid);
        if (!fundTransferSubDataEntities.isEmpty()) {
            physicalDeleteSubBatch(corpid, fundTransferSubDataEntities, IndexTypeEnum.IDX_SAAS_FUND_TRANSFER_SUB);
        }
    }

    @Override
    public FormDataAddVO afterSave(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, SaveVO saveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        Long dataId = saveVO.getDataId();
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        try {
            if (Objects.equals(1, saveVO.getNoApprovalRequired())) {
                SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
                BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
                packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);
                saasFormSaveDTO.setSaasNeedRedundantAttrPoJo(beforeSaveVO.getSaasNeedRedundantAttrPojo());
                fundTransferService.afterSave(saasFormSaveDTO);
                // log
                afterSaveLog(formDataAddDTO, paasFormEntity, paasFormDataEntity, saveVO, beforeSaveVO);
                // 动态处理
                dynamicHelp.addLinkData(saasFormSaveDTO);
                // api
                apiHook(formDataAddDTO, saveVO, beforeSaveVO);
                // 业务规则
                activeRule(formDataAddDTO, beforeSaveVO, paasFormDataEntity, beforeSaveVO.getPaasFormEntityExt());
                formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
                formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
                formDataAddVO.setDataId(saveVO.getDataId());
                formDataAddVO.setFormDataId(saveVO.getDataId());
            } else {
                formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_PROCESS_RETURN_MSG));
                formDataAddVO.setCode(PaasConstant.FORM_ADD_PROCESS_RETURN_CODE);
            }
            return formDataAddVO;
        }  catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveFundTransferRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveFundTransferRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    /**
     * 资金调拨单相关es回滚，除了回滚资金调拨单、还有资金账户流水、还有资金账户信息需要更新
     *
     * @param dataId 资金调拨单id
     * @param corpid
     * @param saasMark
     * @param businessType
     * @throws XbbException
     */
    public void saveFundTransferRollBack(Long dataId, String corpid, Integer saasMark, Integer businessType) throws XbbException {
        try {
            //回滚资金调拨单
            saveRollBack(dataId, corpid ,saasMark, businessType);
            //回滚资金账户流水
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("sheetIdIn", Arrays.asList(dataId));
            param.put("corpid", corpid);
            param.put("types", Arrays.asList(FundAccountFlowTypeEnum.FUND_TRANSFER_IN.getCode(), FundAccountFlowTypeEnum.FUND_TRANSFER_OUT.getCode()));
            List<FundAccountFlowEntity> fundAccountFlowEntities =  fundAccountFlowModel.findEntitys(param);
            List<Long> fundAccountFlowIdList = fundAccountFlowEntities.stream().map(e -> e.getId()).collect(Collectors.toList());
            if (CollectionsUtil.isNotEmpty(fundAccountFlowIdList)) {
                paasEsModel.physicalDeleteBatch(fundAccountFlowIdList, corpid, IndexTypeEnum.IDX_FUND_ACCOUNT_FLOW);
            }
        } catch (Exception e) {
            LOG.error("FundTransferDataServiceImpl.saveFundTransferRollBack 回滚失败：", e);
        }

    }

    @Override
    public SaveVO saveForWorkflow(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Long dataId = 0L;
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        Long refundId = null;
        try {
            UserVO userVO = getUserName(formDataAddDTO, paasFormDataEntity);
            Integer noApprovalRequired = beforeSaveVO.getNoApprovalRequired();
            JSONObject data = paasFormDataEntity.getData();
            Object richTextData = removeRichText(data);
            JSONObject originData = (JSONObject) data.clone();

            FormDataUtil.removeSystemData(data);
            FundTransferEntity fundTransferEntity = new FundTransferEntity();
            BeanUtil.copyProperties(paasFormDataEntity, fundTransferEntity);
            fundTransferModel.insert(fundTransferEntity);
            dataId = fundTransferEntity.getId();
            // 设置属性用于返回
            setPartialAttributes(dataId, fundTransferEntity.getSubFormData(), fundTransferEntity.getData(), fundTransferEntity.getAddTime(),
                    fundTransferEntity.getUpdateTime(), paasFormDataEntity, beforeSaveVO);

            //文件柜数据保存
//                saveFile(formDataAddDTO, paasFormDataEntity, userVO);
            //富文本数据保存
            saveRichText(formDataAddDTO, paasFormDataEntity, richTextData);
            paasFormDataEntity.setData(originData);
            return new SaveVO(noApprovalRequired, paasFormDataEntity, dataId, userVO, refundId);
        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public FormDataAddVO afterSaveForWorkflow(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, SaveVO saveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        Long dataId = saveVO.getDataId();
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        try {
            SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
            BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
            packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);
            saasFormSaveDTO.setSaasNeedRedundantAttrPoJo(beforeSaveVO.getSaasNeedRedundantAttrPojo());
            fundTransferService.afterSaveForWorkflow(saasFormSaveDTO);
//            // log
//            afterSaveLog(formDataAddDTO, paasFormDataEntity, saveVO, beforeSaveVO);
//            // api
//            apiHook(formDataAddDTO, saveVO, beforeSaveVO);
//            // 业务规则
//            activeRule(formDataAddDTO, beforeSaveVO, paasFormDataEntity, beforeSaveVO.getPaasFormEntityExt());
            formDataAddVO.setDataId(saveVO.getDataId());
            formDataAddVO.setFormDataId(saveVO.getDataId());
            formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
            formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
            return formDataAddVO;
//        }  catch (XbbException e) {
//            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
//            saveFundTransferRollBack(dataId, corpid, saasMark, businessType);
//            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveFundTransferRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }
}
